package com.sync.data.common.util;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.TypeUtil;
import com.sync.data.common.annotation.FieldRelation;
import com.sync.data.common.annotation.ObjectInfo;
import com.sync.data.common.model.RelatedObjectModel;

import javax.persistence.DiscriminatorValue;
import javax.persistence.EntityManager;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.metamodel.EntityType;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author liquanchang
 */
public class EntityUtils {

    /**
     * 获取指定Entity
     * @param entityManager
     * @param entityName
     * @return
     */
    public static Class<?> getEntityClass(EntityManager entityManager, String entityName) {
        for (EntityType<?> entity : entityManager.getMetamodel().getEntities()) {
            if (entityName.equals(ClassUtil.getClassName(entity.getJavaType(),true))) {
                return entity.getJavaType();
            }
        }

        return null;
    }

    /**
     * 获取所有Entity对象
     * @param entityManager
     * @return
     */
    public static List<Class<?>> getAllEntityClass(EntityManager entityManager) {
        List<Class<?>> classList = new ArrayList<>();
        for (EntityType<?> entity : entityManager.getMetamodel().getEntities()) {
            classList.add(entity.getJavaType());
        }
        return classList;
    }

    public static List<RelatedObjectModel> getRelatedObject(EntityManager entityManager, String entityName) {
        List<RelatedObjectModel> relatedObjectModels = new ArrayList<>();
        for (EntityType<?> entity : entityManager.getMetamodel().getEntities()) {
            Class<?> entityJavaClass = entity.getJavaType();

            ObjectInfo objectInfo = entityJavaClass.getAnnotation(ObjectInfo.class);

            List<Field> allFields = ClassUtils.getAllFields(entityJavaClass);
            for(Field field : allFields){
                OneToMany oneToMany = field.getAnnotation(OneToMany.class);
                OneToOne oneToOne = field.getAnnotation(OneToOne.class);
                FieldRelation fieldRelation = field.getAnnotation(FieldRelation.class);

                if(ObjectUtil.isNotNull(oneToMany)){
                    Type fieldType = TypeUtil.getFieldType(entityJavaClass, field.getName());
                    String className = extractClassName(fieldType.getTypeName());
                    if(entityName.equals(className)){
                        RelatedObjectModel relatedObjectModel = new RelatedObjectModel();
                        relatedObjectModel.setObject(ClassUtil.getClassName(entityJavaClass,true));
                        relatedObjectModel.setObjectKey(field.getName());
                        if(ObjectUtil.isNotNull(fieldRelation)){
                            relatedObjectModel.setParentObjectKey(fieldRelation.parentObjectKey());
                        }
                        if(ObjectUtil.isNotNull(objectInfo)){
                            relatedObjectModel.setRelation(objectInfo.relation());
                        }
                        relatedObjectModels.add(relatedObjectModel);

                    }
                }

                if(ObjectUtil.isNotNull(oneToOne)){
                    String className = ClassUtil.getClassName(field.getType(), true);
                    if(entityName.equals(className)){
                        RelatedObjectModel relatedObjectModel = new RelatedObjectModel();
                        relatedObjectModel.setObject(ClassUtil.getClassName(entityJavaClass,true));
                        relatedObjectModel.setObjectKey(field.getName());
                        if(ObjectUtil.isNotNull(fieldRelation)){
                            relatedObjectModel.setParentObjectKey(fieldRelation.parentObjectKey());
                        }
                        if(ObjectUtil.isNotNull(objectInfo)){
                            relatedObjectModel.setRelation(objectInfo.relation());
                        }
                        relatedObjectModels.add(relatedObjectModel);
                    }
                }

            }
        }
        return relatedObjectModels;
    }

    public static List<String> getSubObject(EntityManager entityManager, String entityName) {

        List<String> subObjects = new ArrayList<>();

        Class<?> entityClass = getEntityClass(entityManager, entityName);

        DiscriminatorValue discriminatorValue = entityClass.getAnnotation(DiscriminatorValue.class);

        if(ObjectUtil.isNotNull(discriminatorValue)){
            for (EntityType<?> entity : entityManager.getMetamodel().getEntities()) {

                Class<?> entityJavaClass = entity.getJavaType();
                Class<?> superclass = entityJavaClass.getSuperclass();

                String superClass = ClassUtil.getClassName(superclass, true);

                if(entityName.equals(superClass)){
                    subObjects.add(superClass);
                }
            }
        }

        return subObjects;
    }

    /**
     * 获取全部Entity
     * @param entityManager
     * @return
     */
    public static List<String> getAllEntity(EntityManager entityManager) {

        List<String> entities = new ArrayList<>();

        for (EntityType<?> entity : entityManager.getMetamodel().getEntities()) {
            entities.add(ClassUtil.getClassName(entity.getJavaType(),true));
        }

        Collections.sort(entities);

        return entities;
    }

    /**
     * 获取范型类名
     * @param typeName
     * @return
     */
    private static String extractClassName(String typeName) {
        String[] strings = typeName.split("\\.");
        return strings[strings.length - 1].replaceAll(">", "");
    }

}
